package com.wei.czz.framework.annex.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.enums.annex.AnnexConditionEnum;
import com.wei.czz.common.enums.annex.AnnexFieldCompareModeEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.vo.annex.AnnexConfigConditionVo;
import com.wei.czz.common.vo.annex.AnnexConfigJsonVo;
import com.wei.czz.common.vo.annex.AnnexConfigVo;
import com.wei.czz.framework.annex.dao.AnnexConfigDao;
import com.wei.czz.framework.annex.entity.AnnexConfigEntity;
import com.wei.czz.framework.annex.service.AnnexConfigService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2024-01-18 15:42:24
 * className: AnnexFieldServiceImpl
 * version: 1.0
 * description:
 */
@Service("annetFieldService")
@AllArgsConstructor
public class AnnexConfigServiceImpl extends ServiceImpl<AnnexConfigDao, AnnexConfigEntity> implements AnnexConfigService {

    private static final Logger log = LoggerFactory.getLogger(AnnexConfigServiceImpl.class);

    @Transactional
    @Override
    public void saveAnnexConfig(Long preId, List<AnnexConfigVo> configList) {
        if (CollectionUtils.isEmpty(configList)) {
            log.warn("传入的附件动态配置列表为空");
            return;
        }
        /*
            查询已有字段主键
         */
        Set<Long> idSet = baseMapper.selectId(preId, CommonEnum.ZERO.getValue());

        /*
            查询已有字段
         */
        List<Long> idList = configList.stream()
                .map(AnnexConfigVo::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        Map<Long, AnnexConfigEntity> annexConfigMap = new HashMap<>();
        if (!idList.isEmpty()) {
            List<AnnexConfigEntity> annexConfigList = baseMapper.selectBatchIds(idList);
            annexConfigMap = annexConfigList.stream()
                    .peek(annexField -> {
                        // 清理正在操作的字段主键
                        idSet.remove(annexField.getId());
                    })
                    .collect(Collectors.toMap(AnnexConfigEntity::getId, Function.identity()));
        }
        List<AnnexConfigEntity> saveList = new ArrayList<>();
        List<AnnexConfigEntity> updateList = new ArrayList<>();
        for (AnnexConfigVo annexConfigVo : configList) {
            AnnexConfigEntity annexConfig = annexConfigMap.get(annexConfigVo.getId());
            boolean isSave = Objects.isNull(annexConfig);

            annexConfig = this.buildAnnexField(annexConfigVo, annexConfig);
            annexConfig.setPreId(preId);
            if (isSave) {
                saveList.add(annexConfig);
            } else {
                updateList.add(annexConfig);
            }
        }
        if (!saveList.isEmpty()) {
            // 保存
            boolean bool = this.saveBatch(saveList);
            log.info("批量保存附件动态配置完成。bool={}", bool);
        }
        if (!updateList.isEmpty()) {
            boolean bool = this.updateBatchById(updateList);
            log.info("批量修改附件动态配置完成。bool={}", bool);
        }
        if (!idSet.isEmpty()) {
            UserPo userPo = SecurityUtils.getUser();
            Date date = new Date();

            LambdaUpdateWrapper<AnnexConfigEntity> annexConfigLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            // 设置字段值
            annexConfigLambdaUpdateWrapper.set(AnnexConfigEntity::getDeleteStatus, CommonEnum.ONE.getValue())
                    .set(AnnexConfigEntity::getUpdateTime, date)
                    .set(AnnexConfigEntity::getUpdateUser, userPo.getUsername())
                    .set(AnnexConfigEntity::getUpdateUserId, userPo.getUserId());
            // 匹配
            annexConfigLambdaUpdateWrapper.in(AnnexConfigEntity::getId, idSet)
                    .eq(AnnexConfigEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
            // 删除
            int count = baseMapper.update(null, annexConfigLambdaUpdateWrapper);
            log.info("删除附件动态配置完成。count={}", count);
        }
    }

    @Transactional
    @Override
    public void batchSaveAnnexConfig(List<AnnexConfigEntity> annexConfigList) {
        boolean bool = this.saveBatch(annexConfigList);
        log.info("批量保存附件动态配置完成。bool={}", bool);
    }

    @Override
    public List<AnnexConfigEntity> getAnnexConfigList(Long preId, List<Long> groupIdList) {
        if (Objects.isNull(preId) && CollectionUtils.isEmpty(groupIdList)) {
            log.info("查询附件配置，入参错误");
            throw new CzzException();
        }
        LambdaQueryWrapper<AnnexConfigEntity> annexConfigLambdaQueryWrapper = new LambdaQueryWrapper<>();
        annexConfigLambdaQueryWrapper.eq(Objects.nonNull(preId), AnnexConfigEntity::getPreId, preId)
                .in(!CollectionUtils.isEmpty(groupIdList), AnnexConfigEntity::getGroupId, groupIdList)
                .eq(AnnexConfigEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        List<AnnexConfigEntity> annexFieldList = baseMapper.selectList(annexConfigLambdaQueryWrapper);
        log.info("查询附件配置完成。preId={} groupIdList={} isEmpty={}", preId, groupIdList, annexFieldList.isEmpty());
        return annexFieldList;
    }

    /**
     * 构造附件动态配置对象
     * @param annexConfigVo 参数对象
     * @param annexConfig   附件动态配置对象
     * @return 附件动态配置对象
     */
    private AnnexConfigEntity buildAnnexField(AnnexConfigVo annexConfigVo, AnnexConfigEntity annexConfig) {
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();
        boolean isSave = Objects.isNull(annexConfig);

        AnnexConfigJsonVo annexConfigJsonVo = annexConfigVo.getConfigJson();
        // 构造条件表达式
        String expression = this.buildExpression(annexConfigJsonVo.getConditionList());
        annexConfigJsonVo.setExpression(expression);

        if (isSave) {
            annexConfig = new AnnexConfigEntity();
        }
        annexConfig.setGroupId(annexConfigVo.getGroupId())
                .setConfigJson(JSON.toJSONString(annexConfigJsonVo))
                .setSort(annexConfigVo.getSort())
                .setUpdateTime(date)
                .setUpdateUser(userPo.getUsername())
                .setUpdateUserId(userPo.getUserId());
        if (isSave) {
            annexConfig.setDeleteStatus(CommonEnum.ZERO.getValue())
                    .setCreateTime(date)
                    .setCreateUser(userPo.getUsername())
                    .setCreateUserId(userPo.getUserId());
        }
        return annexConfig;
    }

    /**
     * 构造条件表达式
     * @param conditionList 条件列表
     * @return 条件表达式
     */
    private String buildExpression(List<AnnexConfigConditionVo> conditionList) {
        if (CollectionUtils.isEmpty(conditionList)) {
            log.info("字段条件列表为空");
            return StringUtils.EMPTY;
        }
        StringBuilder sb = new StringBuilder();
        for (AnnexConfigConditionVo annexConfigConditionVo : conditionList) {
            sb.append("and (");

            AnnexConditionEnum annexConditionEnum = AnnexConditionEnum.get(annexConfigConditionVo.getValue());
            if (Objects.isNull(annexConditionEnum)) {
                log.error("字段条件枚举对象不存在。value={}", annexConfigConditionVo.getValue());
                throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "附件字段条件枚举不存在");
            }
            AnnexFieldCompareModeEnum annexFieldCompareModeEnum =
                    AnnexFieldCompareModeEnum.get(annexConfigConditionVo.getCompareMode());
            if (Objects.isNull(annexFieldCompareModeEnum)) {
                log.error("字段比较方式枚举对象不存在。value={}", annexConfigConditionVo.getValue());
                throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "附件字段比较方式枚举不存在");
            }
            switch (annexFieldCompareModeEnum) {
                case EQUALS_NUMBER:
                case EQUALS_STRING:
                    sb.append('#').append(annexConditionEnum.getField()).append(" == ").append("#v")
                            .append(annexConditionEnum.getField());
                    break;
                case NOT_EQUALS_NUMBER:
                case NOT_EQUALS_STRING:
                    sb.append("not #").append(annexConditionEnum.getField()).append(" == ")
                            .append("#v").append(annexConditionEnum.getField());
                    break;
                case CONTAIN_NUMBER:
                case CONTAIN_STRING:
                    sb.append("not #").append(annexConditionEnum.getField()).append(".contains(#v")
                            .append(annexConditionEnum.getField());
                    break;
                case NOT_CONTAIN_NUMBER:
                case NOT_CONTAIN_STRING:
                    sb.append("not #").append(annexConditionEnum.getField()).append(".contains(#v")
                            .append(annexConditionEnum.getField()).append(')');
                case RANGE_NUMBER:
                case RANGE_DATETIME:
                case RANGE_DATE:
                    sb.append(annexConditionEnum.getField()).append("Min <= #").append(annexConditionEnum.getField())
                            .append(" and #v").append(annexConditionEnum.getField()).append(" <= ")
                            .append(annexConditionEnum.getField()).append("Max");
                    break;
                default:
                    break;
            }

            sb.append(')');
        }
        // 去除最前面的’and ‘
        return sb.substring(4);
    }
}